home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 June: Reference Library / Dev.CD Jun 99 RL Disk 1.toast / What's New / Development Kits / Mac_OS_USB_DDK_v1.2 / Examples / PrinterClassDriver / Chooser.cp next >
Encoding:
Text File  |  1999-04-15  |  33.4 KB  |  1,162 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Chooser.cp
  3.  
  4.     Contains:    Chooser PACK code to support USB and serial printers
  5.  
  6.  
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History:
  11.  
  12.         10 Jun 98    gp        Lock our global area
  13.         9  Jun 98    gp        Clear the handle when creating the global storage
  14.                             Remove old global rsrc if its still there
  15.         8  May 98    gp        If we don't support USB then no need to init the name registry
  16.                             ptrs. This will prevent the name registry alert from
  17.                             displaying on non PCI PowerMacs if we only support serial.
  18.         8  May 98    gp        Moved creation of model index array to InitPack
  19.         21 Apr 98    gp        If only 1 USB printer is listed and no previous selection
  20.                             then select it. Added new routines to save selected printer's
  21.                             name and USB path If previously selected printer is not available
  22.                             display an alert.
  23.         27 Mar 98    gp        Routines to access connection info from in rsrc
  24.         26 Mar 98    gp        Release model index storage. Add support for serial ports
  25.         25 Mar 98     gp        Change code to store our global space our rsrc
  26.         21 Mar 98     gp        Created
  27.  
  28.     To Do:
  29. */
  30.  
  31. #ifndef __Chooser__
  32. #include "Chooser.h"
  33. #endif
  34.  
  35. #ifndef __COMMON__
  36. #include "Common.h"
  37. #endif
  38.  
  39. #ifndef __UTILS__
  40. #include "Utils.h"
  41. #endif
  42.  
  43. #ifndef __DEVICES__
  44. #include <Devices.h>
  45. #endif
  46.  
  47. #ifndef __RESOURCES__
  48. #include <Resources.h>
  49. #endif
  50.  
  51. #ifndef __TEXTUTILS__
  52. #include <TextUtils.h>
  53. #endif
  54.  
  55. #ifndef __COMMRESOURCES__
  56. #include <CommResources.h>
  57. #endif
  58.  
  59. #ifndef __CRMSERIALDEVICES__
  60. #include <CRMSerialDevices.h>
  61. #endif
  62.  
  63. #ifndef __MIXEDMODE__
  64. #include <MixedMode.h>
  65. #endif
  66.  
  67. #ifndef __CODEFRAGMENTS__
  68. #include <CodeFragments.h>
  69. #endif
  70.  
  71. #ifndef __DIALOGS__
  72. #include <dialogs.h>
  73. #endif
  74.  
  75. #ifndef __SafeNameRegistry__
  76. #include "SafeNameRegistry.h"
  77. #endif
  78.  
  79. /******************************************************************************
  80.     Typedefs
  81.  ******************************************************************************/
  82.  
  83. // This structure is passed to AddPrintertoList (a callback routine) from
  84. // SearchForUSBPrinters. Its used to hold data which is needed to add a
  85. // printer name to the Chooser's printer list
  86. typedef struct
  87. {
  88.     ListHandle    list;            // the printer list
  89.     Cell        insertcell;        // where to insert an entry
  90.     short        modelIndex;        // index into STR# holding printer models supported
  91. } AddPrintertoListCallBackStruct, *AddPrintertoListCallBackStructPtr;
  92.  
  93. // This structure is passed to AddPorttoList (a callback routine) from
  94. // SearchForSerialPorts. Its used to hold data which is needed to add a
  95. // serial port to the Chooser's printer list
  96. typedef struct
  97. {
  98.     ListHandle    list;            // the printer list
  99.     Cell        insertcell;        // where to insert an entry
  100. } AddPorttoListCallBackStruct, *AddPorttoListCallBackStructPtr;
  101.  
  102. // typedef for callback routine used in SearchForUSBPrinters when a printer
  103. // entry is found in the name registry
  104. typedef void (*FoundUSBPrinterProcPtr) ( RegEntryID* aPrinterEntry, void* userData);
  105.  
  106. // typedef for callback routine used in SearchForSerialPorts when a port
  107. // entry is found in the name registry
  108. typedef void (*FoundSerialPortProcPtr) ( CRMSerialPtr aPort, void* userData);
  109.  
  110. /******************************************************************************
  111.     Prototypes
  112.  ******************************************************************************/
  113.  
  114. short    CountUSBPrinters(void);
  115. void    FillPrinterList( ListHandle list );
  116. void    AddPrintertoList( RegEntryID* aPrinterEntry, void* userData );
  117. void    CountAPrinter( RegEntryID* aPrinterEntry, void* userData );
  118. void    SearchForUSBPrinters( StringPtr modelPath, FoundUSBPrinterProcPtr callback, void* userData );
  119.  
  120. short    CountSerialPorts(void);
  121. void    AddPorttoList( CRMSerialPtr aPort, void* userData );
  122. void    CountAPort(  CRMSerialPtr aPort, void* userData );
  123. void    SearchForSerialPorts(FoundSerialPortProcPtr callback, void* userData);
  124.  
  125. OSErr    ShowSelection (ListHandle list, StringPtr zoneName);
  126. OSErr    Select (ListHandle list, StringPtr zoneName, long rowNum);
  127.  
  128. void    SetConnectionType(short    type);
  129. short    GetConnectionType(void);
  130. OSErr    InitPack(void);
  131.  
  132. Boolean    SaveSelectedUSBPrinter( Cell selectedCell, ListHandle list );
  133. void    SaveSelectedPrinterName( Cell selectedCell, ListHandle list);
  134. Handle    GetLastSelectedUSBPrinter();
  135.  
  136. /******************************************************************************
  137.     Constants
  138.  ******************************************************************************/
  139.  
  140. #define        kHilited    0
  141. #define        kUnHilited    255
  142.  
  143. #define        kGlobalType        'wxyz'        // made up type
  144. #define        kGlobalID        128
  145.  
  146. #define        kConnectionType        'CTYP'
  147. #define        kConnectionTypeID    1000
  148.  
  149. // Possible selected types. Used in ConnectionType rsrc
  150. #define        kNone            0
  151. #define        kSerial            1
  152. #define        kUSB            2
  153.  
  154. #define     kAPortName    "\p.AIn"    // To compare input device name when searching serial devices in the Comm Tool Box's List
  155. #define        kBPortName    "\p.BIn"    // To comapre input device name when searching serial devices in the Comm Tool Box's List
  156.  
  157. #define        kPrinterNotAvailable    3100
  158. /*-----------------------------------------------------------------------------*
  159.  
  160.     SaveSelectedUSBPrinter
  161.     
  162.     Desc:        Saves the name registry path of the selected printer
  163.  
  164.     In:            - the cell of the selected printer
  165.                 - the Chooser's printer list
  166.                 - the row of the selected cell
  167.                 
  168.     Out:        true if the path was saved
  169.                 false if the path wasn't saved
  170.  
  171.     History:
  172.     
  173.     21 Apr 98    gp        Created
  174.     
  175.  *-----------------------------------------------------------------------------*/
  176. Boolean    SaveSelectedUSBPrinter( Cell selectedCell, ListHandle list )
  177. {
  178.     Handle        lastPrinterString=nil;    // the previous selected printer 
  179.     Str255         selectedPrinterName;    // name of the selected printer
  180.     Str255        modelString;    // path in name registry of printer model
  181.     Boolean        saved=false;            // was the selected printer saved properly
  182.  
  183.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  184.  
  185.     gGlobals = GetGlobalStorage();
  186.  
  187.     // Get the name of the printer that was selected out of the list
  188.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  189.     // get the last selected printer
  190.     lastPrinterString = GetLastSelectedUSBPrinter();
  191.  
  192.     // get the model path
  193.     GetIndString(modelString, kUSBModelPathString, *((**gGlobals).modelIndex+selectedCell.v) );
  194.     if( modelString[0] != 0 && lastPrinterString != nil) 
  195.     {                
  196.         Handle    tempHandle=nil;
  197.         // create the selected printer's name registry path
  198.         AppendPStr( (StringPtr) modelString, "\p:" );
  199.         AppendPStr( (StringPtr) modelString, selectedPrinterName );
  200.         
  201.         HLock( lastPrinterString );
  202.         BlockMove( modelString, *lastPrinterString, modelString[0]+1 );
  203.         HUnlock( lastPrinterString );
  204.  
  205.         // save the selected printers's name registry path
  206.         ChangedResource( lastPrinterString );
  207.         SetConnectionType( kUSB );
  208.         
  209.         WriteResource(lastPrinterString);
  210.         saved = true;
  211.     }
  212.     return saved;
  213. }
  214.  
  215. /*-----------------------------------------------------------------------------*
  216.  
  217.     GetLastSelectedUSBPrinter
  218.     
  219.     Desc:        Returns the name registry path of the last selected USB printer
  220.  
  221.     In:            None
  222.                 
  223.     Out:        Handle to a STR containing the name registry path of the last
  224.                 selected USB printer
  225.  
  226.     History:
  227.     
  228.     21 Apr 98    gp        Created
  229.     
  230.  *-----------------------------------------------------------------------------*/
  231. Handle    GetLastSelectedUSBPrinter()
  232. {
  233.     Handle            printerString=nil;    // the full path in name registry of last selected USB printer
  234.  
  235.     printerString = Get1Resource( 'STR ', kUSBPrinterPathString );
  236.     if( printerString == nil ) {
  237.         DebugStr("\pIn GetLastSelectedUSBPrinter. THIS SHOULD NEVER HAPPEN");
  238.     }
  239.     return printerString;
  240. }
  241.  
  242. /*-----------------------------------------------------------------------------*
  243.  
  244.     SaveSelectedPrinterName
  245.     
  246.     Desc:        Saves the name of the selected printer in our rsrc
  247.  
  248.     In:            - the cell of the selected printer
  249.                 - the Choosers printer list handle
  250.                 
  251.     Out:        None
  252.  
  253.     History:
  254.     
  255.     21 Apr 98    gp        Created
  256.     
  257.  *-----------------------------------------------------------------------------*/
  258. void    SaveSelectedPrinterName( Cell selectedCell, ListHandle list)
  259. {
  260.     Handle            printerString=nil;        // path in name registry of current USB printer
  261.     Str255             selectedPrinterName;            // name of the selected printer
  262.  
  263.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  264.  
  265.     // save the name of the printer
  266.     printerString = (Handle) Get1Resource( 'STR ', kPrinterNameString );
  267.     if( selectedPrinterName[0] != 0 && printerString != nil) 
  268.     {
  269.         HLock( printerString );
  270.         BlockMove( selectedPrinterName, *printerString, selectedPrinterName[0]+1 );
  271.         HUnlock( printerString );
  272.  
  273.         // save the newly selected printer's name
  274.         ChangedResource( printerString );
  275.         WriteResource(printerString);
  276.     }
  277.  
  278. }
  279.  
  280. /*-----------------------------------------------------------------------------*
  281.  
  282.     GetConnectionType
  283.     
  284.     Desc:        Gets the connection type for the last selected printer
  285.                 from our rsrc
  286.  
  287.     In:            None
  288.                 
  289.     Out:        kNone, kSerial or kUSB
  290.  
  291.     History:
  292.     
  293.     27 Mar 98    gp        Created
  294.     
  295.  *-----------------------------------------------------------------------------*/
  296. short    GetConnectionType(void)
  297. {
  298.     Handle    connection;
  299.  
  300.     connection = (Handle) Get1Resource( kConnectionType, kConnectionTypeID );
  301.     return (**(short**)connection);
  302.  
  303. }
  304.  
  305. /*-----------------------------------------------------------------------------*
  306.  
  307.     SetConnectionType
  308.     
  309.     Desc:        Saves the connection type of the selected printer in our rsrc
  310.  
  311.     In:            kNone, kSerial or kUSB
  312.                 
  313.     Out:        None
  314.     
  315.     History:
  316.     
  317.     27 Mar 98    gp        Created
  318.     
  319.  *-----------------------------------------------------------------------------*/
  320. void    SetConnectionType(short    type)
  321. {
  322.     Handle    connection;
  323.  
  324.     connection = (Handle) Get1Resource( kConnectionType, kConnectionTypeID );
  325.     (**(short**)connection) = type;
  326.     ChangedResource( connection );
  327.     WriteResource( connection );
  328. }
  329.  
  330. /*-----------------------------------------------------------------------------*
  331.  
  332.     CountAPort
  333.     
  334.     Desc:        Callback routine for CountSerialPorts. It increments the
  335.                 ptr to user data thus incrementing the count of serial ports.
  336.  
  337.     In:            - A port to a CRMSerialPtr struct
  338.                 - A ptr to user data
  339.  
  340.     Out:        None
  341.     
  342.     History:
  343.     
  344.     26 Mar 98    gp        Created
  345.     
  346.  *-----------------------------------------------------------------------------*/
  347. void    CountAPort(  CRMSerialPtr aPort, void* userData )
  348. {
  349.     // we're only interested in .ain and .bin
  350.     if ( (PStrEqualCaseInsensitive((unsigned char*) kBPortName, *(aPort->inputDriverName)) ) ||
  351.         (PStrEqualCaseInsensitive((unsigned char*) kAPortName, *(aPort->inputDriverName)) ))
  352.     {
  353.             *((short*) userData) +=1;
  354.     }
  355. }
  356.  
  357. /*-----------------------------------------------------------------------------*
  358.  
  359.     AddPorttoList
  360.     
  361.     Desc:        Adds a serial port the the Chooser's list. We're only interested
  362.                 in modem and printer ports
  363.  
  364.     In:            - A port to a CRMSerialPtr struct
  365.                 - A ptr to user data. This should be a ptr to a 
  366.                   AddPorttoListCallBackStruct
  367.  
  368.     Out:        None
  369.     
  370.     History:
  371.     
  372.     26 Mar 98    gp        Created
  373.     
  374.  *-----------------------------------------------------------------------------*/
  375. void    AddPorttoList( CRMSerialPtr aPort, void* userData )
  376. {
  377.     AddPorttoListCallBackStructPtr     addPortStruct=(AddPorttoListCallBackStructPtr) userData;
  378.  
  379.     // we're only interested in .ain and .bin
  380.     if ( PStrEqualCaseInsensitive((unsigned char*) kBPortName, *(aPort->inputDriverName)) )
  381.     {
  382.         LAddRow(1, addPortStruct->insertcell.v, addPortStruct->list);
  383.         LSetCell( "Printer", 7, addPortStruct->insertcell, addPortStruct->list );
  384.         addPortStruct->insertcell.v++;
  385.     }
  386.     
  387.     if ( PStrEqualCaseInsensitive((unsigned char*) kAPortName, *(aPort->inputDriverName)) )
  388.     {
  389.         LAddRow(1, addPortStruct->insertcell.v, addPortStruct->list);
  390.         LSetCell( "Modem", 5, addPortStruct->insertcell, addPortStruct->list );
  391.         addPortStruct->insertcell.v++;
  392.     }
  393. }
  394.  
  395. /*-----------------------------------------------------------------------------*
  396.  
  397.     CountSerialPorts
  398.     
  399.     Desc:        Returns the number of serial ports
  400.  
  401.     In:            None
  402.                 
  403.     Out:        The number of serial ports
  404.     
  405.     History:
  406.     
  407.     26 Mar 98    gp        Created
  408.     
  409.  *-----------------------------------------------------------------------------*/
  410. short    CountSerialPorts(void)
  411. {
  412.     short    numberOfPorts=0;
  413.  
  414.     SearchForSerialPorts( (FoundSerialPortProcPtr) &CountAPort, &numberOfPorts );
  415.  
  416.     return numberOfPorts;
  417. }
  418.  
  419. /*-----------------------------------------------------------------------------*
  420.  
  421.     SearchForSerialPorts
  422.     
  423.     Desc:        Searchs for serial ports on this machine
  424.  
  425.     In:            - A callback routine which gets called when a printer is found
  426.                 - A ptr to user data
  427.  
  428.     Out:        None
  429.     
  430.     History:
  431.     
  432.     26 Mar 98    gp        Created
  433.     
  434.  *-----------------------------------------------------------------------------*/
  435. void    SearchForSerialPorts(FoundSerialPortProcPtr callback, void* userData)
  436. {
  437.     CRMErr                theErr;                // comm rsrc manager error
  438.     CRMRec                commRec;            // communications resource manager record
  439.     CRMRecPtr            commRecPtr;            // ptr to a communication resource record in the queue
  440.     CRMSerialPtr        commRecSerialPtr;    // ptr to serial record inside comm resource record
  441.     long            curSerialDeviceID = 0;     // initially set to zero, so we get all serial devices
  442.  
  443.     theErr = InitCRM(); // Initialize the Communications Resource Manager
  444.  
  445.     // now search for serial devices
  446.     while (theErr == noErr)
  447.     {
  448.         commRec.crmDeviceType = crmSerialDevice; // look for serial devices
  449.         commRec.crmDeviceID = curSerialDeviceID; // look for a device number greater than curSerialDeviceID
  450.     
  451.         commRecPtr = &commRec;
  452.         commRecPtr = CRMSearch(commRecPtr);    // Search  queue for each serial device
  453.     
  454.         if (commRecPtr != nil)
  455.         {
  456.             // get the Serial record pointer
  457.             commRecSerialPtr = (CRMSerialPtr)(*commRecPtr).crmAttributes;
  458.             
  459.             callback( commRecSerialPtr, userData);    // found a port
  460.             
  461.             // Set device ID for next search
  462.             curSerialDeviceID = (*commRecPtr).crmDeviceID;
  463.         }
  464.         else
  465.         {
  466.             theErr = 1; // game over, no more serial devices
  467.         }
  468.     }
  469. }
  470.  
  471. /*-----------------------------------------------------------------------------*
  472.  
  473.     SearchForUSBPrinters
  474.     
  475.     Desc:        Searches thru a printer model entry in the name registry
  476.                 looking for a model's printers. When one is found a call is 
  477.                 issued to the clients callback routine for further processing
  478.  
  479.     In:            - A pstring full path in the name registry of a printer model
  480.                 - A callback routine which gets called when a printer is found
  481.                 - A ptr to user data
  482.                 
  483.     Out:        None
  484.     
  485.     History:
  486.     
  487.     24 Feb 98    gp        Created
  488.     
  489.  *-----------------------------------------------------------------------------*/
  490. void    SearchForUSBPrinters( StringPtr modelPath, FoundUSBPrinterProcPtr callback, void* userData )
  491. {
  492.  
  493.     RegEntryID        theModelEntry;        // the model node supported by the driver
  494.     RegEntryID        aPrinterEntry;        // a printer node in the name registry
  495.     RegEntryIterationOp iterOp;            // name registry iterator op code
  496.     RegEntryIter    printerIterator;    // used to iterate child nodes of printer model
  497.     Boolean            donePrinters    = false;    // NameRegistry param tell when we're done
  498.     OSStatus        err             = noErr;    // error from name registry calls
  499.  
  500.     // name registry only deals with c strings
  501.     p2cstr( (StringPtr) modelPath );
  502.  
  503.     // look up the node for the printer model requested
  504.     err = SafeRegistryEntryIDInit(&theModelEntry);
  505.     err = SafeRegistryCStrEntryLookup( nil, (char*) modelPath, &theModelEntry );
  506.  
  507.     if( err == noErr ) 
  508.     {
  509.         // create an iterator to look at the child nodes for our printer model entry
  510.         iterOp = kRegIterChildren;
  511.  
  512.         err = SafeRegistryEntryIterateCreate( &printerIterator );
  513.         err = SafeRegistryEntryIterateSet(&printerIterator, &theModelEntry);
  514.         
  515.         if( err == noErr )
  516.         {
  517.             // look for a model's connected printers
  518.             do
  519.             {
  520.                 err = SafeRegistryEntryIterate( &printerIterator, iterOp, &aPrinterEntry, &donePrinters );
  521.                 if( !donePrinters && err == noErr )
  522.                     callback(&aPrinterEntry, userData);    // found a printer
  523.  
  524.                 iterOp = kRegIterContinue;
  525.             } while( !donePrinters && err == noErr );
  526.             // end while for printers
  527.         }
  528.         SafeRegistryEntryIterateDispose(&printerIterator);
  529.     }
  530.  
  531.     SafeRegistryEntryIDDispose( &theModelEntry );
  532.     c2pstr( (char*) modelPath );
  533.  
  534. }
  535.  
  536. /*-----------------------------------------------------------------------------*
  537.  
  538.     CountAPrinter
  539.     
  540.     Desc:        Callback routine for CountUSBPrinters. It increments the
  541.                 ptr to user data thus incrementing the count of USB printers.
  542.  
  543.     In:            - A printer entry in the name registry
  544.                 - A ptr to user data
  545.                 
  546.     Out:        The number of USB printers in the name registry
  547.     
  548.     History:
  549.     
  550.     24 Feb 98    gp        Created
  551.     
  552.  *-----------------------------------------------------------------------------*/
  553.  
  554. void    CountAPrinter(  RegEntryID* aPrinterEntry, void* userData )
  555. {
  556.     *((short*) userData) +=1;
  557. }
  558.  
  559. /*-----------------------------------------------------------------------------*
  560.  
  561.     CountUSBPrinters
  562.     
  563.     Desc:        Returns the number of connected USB printers associated with this driver
  564.  
  565.     In:            None
  566.                 
  567.     Out:        The number of USB printers in the name registry
  568.     
  569.     History:
  570.     
  571.     24 Feb 98    gp        Created
  572.     
  573.  *-----------------------------------------------------------------------------*/
  574.  
  575. short    CountUSBPrinters()
  576. {
  577.     short            numberOfPrinters=0;    // return value for number of USB printers
  578.     Str255            modelPath;            // pstring path in a supported printer model
  579.     short            i;                    // counter
  580.  
  581.     i=1;
  582.     // read a supported printer's name registry model path
  583.     GetIndString(modelPath, kUSBModelPathString, i);
  584.     
  585.     while( (char*) modelPath[0] != 0 )        // if len is zero then no more models
  586.     {
  587.         SearchForUSBPrinters( modelPath, (FoundUSBPrinterProcPtr) &CountAPrinter, &numberOfPrinters );
  588.         i++;
  589.         // read another supported printer's name registry model path
  590.         GetIndString(modelPath, kUSBModelPathString, i);
  591.     }
  592.  
  593.     return numberOfPrinters;
  594. }
  595.  
  596. /*-----------------------------------------------------------------------------*
  597.  
  598.     AddPrintertoList
  599.     
  600.     Desc:        Adds an USB printer to the Chooser's printer list by extracting
  601.                 the name from the name registry
  602.  
  603.     In:            - A printer entry in the name registry
  604.                 - A ptr to user data. This should be a ptr to a 
  605.                   AddPrintertoListCallBackStruct 
  606.                 
  607.     Out:        The number of USB printers in the name registry
  608.     
  609.     History:
  610.     
  611.     24 Feb 98    gp        Created
  612.     
  613.  *-----------------------------------------------------------------------------*/
  614. void    AddPrintertoList( RegEntryID* aPrinterEntry, void* userData )
  615. {
  616.     OSStatus        err = noErr;        // error from name registry call
  617.     Str255            nodeName;            // the name of the printer
  618.     RegPropertyValueSize    nameSize;    // size of name buffer
  619.     AddPrintertoListCallBackStructPtr     fillListStruct=(AddPrintertoListCallBackStructPtr) userData;
  620.     USBGlobalsHandle    gGlobals=nil;    // our global data area
  621.  
  622.     gGlobals = GetGlobalStorage();
  623.  
  624.     nameSize = sizeof( nodeName );
  625.     // grab name of printer in name registyr
  626.     err = SafeRegistryPropertyGet( aPrinterEntry, "name", &nodeName, &nameSize );
  627.     
  628.     if( err == noErr ) {
  629.         // stick it in the printer list
  630.         LAddRow(1, fillListStruct->insertcell.v, fillListStruct->list);
  631.         LSetCell( nodeName, nameSize-1, fillListStruct->insertcell, fillListStruct->list );
  632.         
  633.         // save info about which model (STR#) this printer belongs to
  634.         *((**gGlobals).modelIndex+fillListStruct->insertcell.v) = fillListStruct->modelIndex;
  635.         fillListStruct->insertcell.v++;
  636.     }
  637. }
  638.  
  639. /*-----------------------------------------------------------------------------*
  640.  
  641.     FillUSBList
  642.     
  643.     Desc:        Fills the printer list with the number of USB printers
  644.  
  645.     In:            - The Chooser's printer list handle
  646.                 
  647.     Out:        None
  648.     
  649.     History:
  650.     
  651.     24 Feb 98    gp        Created
  652.     
  653.  *-----------------------------------------------------------------------------*/
  654. void    FillPrinterList( ListHandle list )
  655. {
  656.     AddPrintertoListCallBackStruct    userData;    // struct needed by callback routine
  657.     AddPorttoListCallBackStruct        userPortData;    // struct needed by callback routine
  658.     Str255        modelPath;                        // pstring path in a supported printer model
  659.     short        i;                                // counter
  660.  
  661.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  662.     
  663.     gGlobals = GetGlobalStorage();
  664.     
  665.     userPortData.insertcell.v = 0;
  666.     // if we support serial ports then list serial ports
  667.     if( (**gGlobals).supportsSerial == true ) {
  668.         userPortData.list = list;
  669.         userPortData.insertcell.h = 0;
  670.  
  671.         // add the serial ports to the chooser list
  672.         SearchForSerialPorts( (FoundSerialPortProcPtr) &AddPorttoList, (void*) &userPortData );
  673.     }
  674.  
  675.     // if we support USB then list USB printers
  676.     if( (**gGlobals).supportsUSB == true ) {
  677.         userData.list = list;
  678.         userData.insertcell.v = userPortData.insertcell.v;
  679.         userData.insertcell.h = 0;
  680.  
  681.         i=1;
  682.         // read a supported printer's name registry model path
  683.         GetIndString(modelPath, kUSBModelPathString, i);
  684.         while( (char*) modelPath[0] != 0 )        // if len is zero then no more models
  685.         {
  686.             userData.modelIndex = i;
  687.             // add the USB printers to the chooser list
  688.             SearchForUSBPrinters( modelPath, (FoundUSBPrinterProcPtr) &AddPrintertoList, (void*) &userData );
  689.             i++;
  690.             // read another supported printer's name registry model path
  691.             GetIndString(modelPath, kUSBModelPathString, i);
  692.         }
  693.     }
  694. }
  695.  
  696. /*-----------------------------------------------------------------------------*
  697.     
  698.     ShowSelection
  699.     
  700.     Desc:        Hilites the currently selected printer in the printer list
  701.  
  702.     In:            - Handle to Mac List Mgr list
  703.                 - Name of zone we are currently in
  704.                 
  705.     Out:        OS error if any
  706.     
  707.     History:
  708.     
  709.     21 Apr 98    gp        If only 1 USB printer is listed and no previous selection
  710.                         then select it. If previously selected printer is not available
  711.                         display an alert.
  712.     9  Apr 98    gp        Use hlock not hunlock. Moved foundcell outside loop
  713.     21 Mar 98    gp        Extract previously selected printer from our rsrc
  714.     24 Feb 98    gp        Created
  715.     
  716.  *-----------------------------------------------------------------------------*/
  717. OSErr    ShowSelection (ListHandle list, StringPtr zoneName)
  718. {
  719.     Cell            cell;                            // used to iterate thru printer list, shows selected cell
  720.     Str255            nameBuffer;                        // selected AT printer is on the net, search for the cell
  721.     Boolean            foundCell = false;                // found a cell with same name as selected printer
  722.     Handle            selectedPrinter;                // name of the selected printer
  723.  
  724.     Str255            modelString;                    // path in name registry of printer model
  725.     Handle            printerString;                    // the full path in name registry of selected USB printer
  726.     RegEntryID        thePrinterEntry;                // the node of the USB printer node selected
  727.     OSStatus        err             = noErr;        // err encountered when calling name registry API
  728.     short            hiliteState = kUnHilited;        // hilite state of the button
  729.     USBGlobalsHandle    gGlobals=nil;                // our global data area
  730.     short            connectionType;                    // what type of printer connection, serial or USB
  731.     
  732.     gGlobals = GetGlobalStorage();
  733.  
  734.     // get the current selected printer out of the rsrc
  735.     printerString = GetLastSelectedUSBPrinter();
  736.     if( printerString == nil ) {
  737.         return noErr;
  738.     }
  739.  
  740.     // extract printer name for use later
  741.     selectedPrinter = (Handle) Get1Resource( 'STR ', kPrinterNameString );
  742.     if(  selectedPrinter == nil)
  743.         return noErr;
  744.     HLock( selectedPrinter );
  745.  
  746.     connectionType = GetConnectionType();
  747.     switch( connectionType ) {
  748.         case kSerial:
  749.             SetPt (&cell, 0, 0);
  750.  
  751.             // look for the port
  752.             while ( (!foundCell) && (cell.v < (*list)->dataBounds.bottom) )
  753.             {
  754.                 GetNameFromCell(nameBuffer, cell, list);
  755.  
  756.                 // if it equals the name of the current cell, we found the printer
  757.                 if ( EqualString( (StringPtr) *selectedPrinter, nameBuffer, true, true) ) {
  758.                     foundCell = true;
  759.                 } else
  760.                     cell.v++;
  761.             }
  762.             if( !foundCell )
  763.                 StopAlert(kPrinterNotAvailable, nil);
  764.             break;
  765.         case kUSB:
  766.             HLock( printerString );
  767.  
  768.             // name registry only deals with c strings
  769.             p2cstr( (StringPtr) *printerString );
  770.  
  771.             // check to make sure printer is still in name registry before selecting
  772.             SafeRegistryEntryIDInit(&thePrinterEntry);
  773.             err = SafeRegistryCStrEntryLookup( nil, (char*) *printerString, &thePrinterEntry );
  774.             
  775.             // clean up
  776.             c2pstr( (char*) *printerString );
  777.             HUnlock( printerString );
  778.             SafeRegistryEntryIDDispose( &thePrinterEntry );
  779.  
  780.             // if printer is no longer connected put up an alert
  781.             if( err ) {
  782.                 StopAlert(kPrinterNotAvailable, nil);
  783.             } else {
  784.                 // since user could have connected or disconnect other printers from USB bus
  785.                 // we need to find the exact place in the list and hilite it
  786.  
  787.                 SetPt (&cell, 0, 0);
  788.  
  789.                 // loop through all the printers in the list seeing if there is a
  790.                 // match for the driver's selected printer
  791.                 while ( (!foundCell) && (cell.v < (*list)->dataBounds.bottom) )
  792.                 {
  793.                     GetNameFromCell(nameBuffer, cell, list);
  794.  
  795.                     // If the name is one of our reserved rows and
  796.                     // it equals the name of the current cell, we found a possible printer
  797.                     
  798.                     if ( EqualString( (StringPtr) *selectedPrinter, nameBuffer, true, true) ) {
  799.  
  800.                         // create name registry full path for this printer and compare it
  801.                         // to the one thats stored in our rsrc
  802.                         
  803.                         // get the printers model
  804.                         GetIndString(modelString, kUSBModelPathString, *((**gGlobals).modelIndex+cell.v) );
  805.                         if( modelString[0] != 0 ) 
  806.                         {
  807.                             // create the path
  808.                             AppendPStr( (StringPtr) modelString, "\p:" );
  809.                             AppendPStr( (StringPtr) modelString, nameBuffer );
  810.                             // check to see if its the same
  811.                             HLock( printerString );
  812.                             if ( EqualString( modelString, (StringPtr) *printerString, true, true) )
  813.                                 foundCell = true;
  814.                             HUnlock( printerString );
  815.                         }
  816.                     }
  817.  
  818.                     if (!foundCell)
  819.                         cell.v++;
  820.                 } // end while
  821.             } // end else
  822.             break;
  823.         default:
  824.             break;
  825.     }
  826.     HUnlock( selectedPrinter );
  827.  
  828.     // if this is our first time and only 1 entry in the list and its USB then select it
  829.     if( ((**gGlobals).supportsUSB == true) && !foundCell && 
  830.         ((*list)->dataBounds.bottom == 1) && ((**gGlobals).numberOfUSBPrinters == 1) ) 
  831.     {
  832.         if( printerString != nil && (**printerString) == 0x0) {
  833.             SetPt(&cell, 0, 0);        // select the 1st cell
  834.  
  835.             if( SaveSelectedUSBPrinter( cell, list ) ) {
  836.                 // save the name of the printer
  837.                 SaveSelectedPrinterName( cell, list );
  838.                 foundCell = true;
  839.             }
  840.         }
  841.     }
  842.  
  843.     // now hilite the selection
  844.     if (foundCell)
  845.     {
  846.         LSetSelect(true, cell, list);
  847.         hiliteState = kHilited;
  848.     }
  849.  
  850.  
  851.     return noErr;
  852. }
  853.  
  854. /*-----------------------------------------------------------------------------*
  855.  
  856.     Select
  857.     
  858.     Desc:        Save the selected printers name and name registry path in our rsrc
  859.  
  860.     In:            - Handle to Mac List Mgr list
  861.                 - Name of zone we are currently in
  862.                 - the row Chooser thinks we should select.
  863.                 
  864.     Out:        OS error if any
  865.     
  866.     History:
  867.     
  868.     21 Mar 98    gp        Save printer name in our rsrc
  869.     24 Feb 98    gp        Created
  870.  
  871. *-----------------------------------------------------------------------------*/
  872. OSErr    Select (ListHandle list, StringPtr zoneName, long rowNum)
  873. {
  874.     
  875.     Str255            modelString;            // path in name registry of printer model
  876.     Handle            printerString=nil;        // path in name registry of current USB printer
  877.     Cell            selectedCell;            // for list processing
  878.     Str32            selectedPrinterName;    // select printer in list
  879.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  880.  
  881.     gGlobals = GetGlobalStorage();
  882.  
  883.     // Find out which row was selected
  884.     SetPt (&selectedCell, 0, 0);
  885.     LGetSelect (true, &selectedCell, list);
  886.  
  887.     // Get the name of the printer that was selected out of the list
  888.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  889.  
  890.     // if nothing selected leave
  891.     if( selectedPrinterName[0] == 0 )
  892.         return noErr;
  893.  
  894.     // serial port selected so just clear the USB model path in the STR rsrc
  895.     if( selectedCell.v < (**gGlobals).numberOfPorts ) {
  896.         printerString = GetLastSelectedUSBPrinter();
  897.         (**printerString) = 0;
  898.         ChangedResource( printerString );
  899.         SetConnectionType( kSerial );
  900.         WriteResource(printerString);
  901.     } else {
  902.         SaveSelectedUSBPrinter( selectedCell, list );
  903.     }
  904.  
  905.     // save the name of the printer
  906.     SaveSelectedPrinterName( selectedCell, list );
  907.     return noErr;
  908. }
  909.  
  910. /*-----------------------------------------------------------------------------*
  911.  
  912.     InitPack
  913.     
  914.     Desc:        Creates our global storage and reads info out of our
  915.                 connection info rsrc
  916.  
  917.     In:            None
  918.  
  919.     Out:        OS error if any
  920.     
  921.     History:
  922.     
  923.     8  May 98    gp        If we don't support USB then no need to init the name registry
  924.                         ptrs. This will prevent the name registry alert from
  925.                         displaying on non PCI PowerMacs if we only support serial.
  926.     8  May 98    gp        Moved creation of model index to here from InitGlobalStorage
  927.     21 Apr 98    gp        If we don't support serial set numberOfPorts to zero
  928.     27 Mar 98    gp        Created
  929.  
  930.  *-----------------------------------------------------------------------------*/
  931. OSErr    InitPack(void)
  932. {
  933.     OSErr                returnValue            = noErr;    // return value
  934.     USBGlobalsHandle    gGlobals            = nil;        // our global data area
  935.     ConnectionTypeHdl    connectionInfo        = nil;
  936.     short                numberOfUSBPrinters = 0;        // number of USB printers detected
  937.     short                numberOfPorts        = 0;        // number of serial ports
  938.  
  939.     // initialize our global storage
  940.     returnValue = InitGlobalStorage();
  941.     if( returnValue == noErr ) 
  942.     {
  943.         gGlobals = GetGlobalStorage();
  944.         connectionInfo = (ConnectionTypeHdl) Get1Resource( kConnectionType, kConnectionTypeID );
  945.         if( connectionInfo != nil )
  946.         {
  947.             (**gGlobals).supportsSerial = ( (**connectionInfo).supportsSerial == 1 );
  948.             (**gGlobals).supportsUSB = ( (**connectionInfo).supportsUSB == 1 );
  949.  
  950.             // if we don't support serial ports then zero out serial port count
  951.             if( (**gGlobals).supportsSerial == false )
  952.                 (**gGlobals).numberOfPorts = 0;
  953.         }
  954.         
  955.         // count USB printers
  956.         if( (**gGlobals).supportsUSB == true )
  957.         {
  958.             // if we support USB we need to init proc ptrs before calling CountUSBPrinters
  959.             InitNameRegistryPtrs();
  960.  
  961.             numberOfUSBPrinters = CountUSBPrinters();
  962.             (**gGlobals).numberOfUSBPrinters = numberOfUSBPrinters;
  963.         } else {
  964.             numberOfUSBPrinters = 0;
  965.             (**gGlobals).numberOfUSBPrinters = 0;
  966.         }
  967.  
  968.         // count serial ports
  969.         if( (**gGlobals).supportsSerial == true ) {
  970.             numberOfPorts = CountSerialPorts();
  971.             (**gGlobals).numberOfPorts = numberOfPorts;
  972.         } else {
  973.             numberOfPorts = 0;
  974.             (**gGlobals).numberOfPorts = 0;
  975.         }
  976.  
  977.         // allocate our index storage
  978.         // there is index space for serial ports which are unused but make the code simpler
  979.         (**gGlobals).modelIndex = (short*) NewPtr( (numberOfPorts+numberOfUSBPrinters)*sizeof(short) );
  980.         if ( (**gGlobals).modelIndex == nil )
  981.         {
  982.             // no index storage so get rid of our globals too
  983.             RemoveGlobalStorage();
  984.             returnValue = memFullErr;
  985.         }
  986.  
  987.     }
  988.     return returnValue;
  989. }
  990.  
  991. /*-----------------------------------------------------------------------------*
  992.  
  993.     Chooser
  994.     
  995.     Desc:        Routines to handle calls from the Chooser
  996.  
  997.     In:            - message from chooser
  998.                 - application id
  999.                 - additional info (varies)
  1000.                 - name of the appletalk zone
  1001.                 - handle to device choices ( printers )
  1002.                 - additional info (varies)
  1003.  
  1004.     Out:        OS error if any
  1005.     
  1006.     History:
  1007.     
  1008.     19 Mar 98    gp        Created
  1009.  
  1010.  *-----------------------------------------------------------------------------*/
  1011. pascal    OSErr    Chooser (short message, short caller, StringPtr objName, StringPtr zoneName, long p1, long p2)
  1012. {
  1013.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  1014.     OSErr returnValue = noErr;                // return value
  1015.  
  1016.     gGlobals = GetGlobalStorage();
  1017.     switch (message)
  1018.     {
  1019.         case chooserInitMsg:
  1020.             returnValue = InitPack();
  1021.             break;
  1022.         case fillListMsg:
  1023.             if( gGlobals != nil )
  1024.                 FillPrinterList( (ListHandle) p1 );
  1025.             break;
  1026.         case getSelMsg:
  1027.             if( gGlobals != nil )
  1028.                 ShowSelection ( (ListHandle)p1, zoneName);
  1029.             break;
  1030.         case selectMsg:
  1031.             if( gGlobals != nil )
  1032.                 Select ( (ListHandle)p1, zoneName, p2);
  1033.             break;
  1034.         case buttonMsg:
  1035.             break;
  1036.         case terminateMsg:
  1037.             RemoveNameRegistryPtrs();
  1038.             RemoveGlobalStorage();
  1039.             break;
  1040.         case deselectMsg:
  1041.             break;
  1042.         default:
  1043.             break;
  1044.     }
  1045.     return returnValue;
  1046. }
  1047.  
  1048. /*-----------------------------------------------------------------------------*
  1049.  
  1050.     InitGlobalStorage
  1051.     
  1052.     Desc:        Creates and stores a block of memory in our rsrc to be
  1053.                 used as global storage
  1054.  
  1055.     In:            none
  1056.  
  1057.     Out:        OS error if any
  1058.     
  1059.     History:
  1060.     
  1061.     10 Jun 98    gp        Lock our global area
  1062.     9  Jun 98    gp        Clear the handle when creating the global storage
  1063.                         Remove old global rsrc if its still there
  1064.     8  May 98    gp        Moved creation of model index to InitPack
  1065.     25 Mar 98    gp        Created
  1066.  
  1067.  *-----------------------------------------------------------------------------*/
  1068. OSErr    InitGlobalStorage(void)
  1069. {
  1070.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  1071.     Handle    globalrsrc;                        // handle to store our global data address
  1072.  
  1073.     // get rid of old global rsrc if its still there
  1074.     globalrsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1075.     if( globalrsrc != nil ) {
  1076.         RemoveResource( globalrsrc );
  1077.         DisposeHandle( globalrsrc );
  1078.     }
  1079.  
  1080.     // allocate our global storage
  1081.     gGlobals = (USBGlobalsHandle) NewHandleClear( sizeof( USBGlobals ) );
  1082.     globalrsrc = NewHandleClear( sizeof( Handle ) );
  1083.     if (gGlobals != nil) 
  1084.     {
  1085.         HLockHi( (Handle) gGlobals );
  1086.         // save our global handle address in our rsrc
  1087.         (** (Handle**) globalrsrc) = (char**) gGlobals;
  1088.         addresource( globalrsrc, kGlobalType, kGlobalID,(char*) "\p");
  1089.  
  1090.         return noErr;
  1091.     } else
  1092.         return memFullErr;
  1093. }
  1094.  
  1095. /*-----------------------------------------------------------------------------*
  1096.  
  1097.     GetGlobalStorage
  1098.     
  1099.     Desc:        Retrieves our global stoarge area
  1100.  
  1101.     In:            none
  1102.  
  1103.     Out:        Handle to our global storage
  1104.     
  1105.     History:
  1106.     
  1107.     25 Mar 98    gp        Created
  1108.  
  1109.  *-----------------------------------------------------------------------------*/
  1110. USBGlobalsHandle    GetGlobalStorage(void)
  1111. {
  1112.     Handle    ourRsrc=nil;                    // handle to ourselves
  1113.  
  1114.     ourRsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1115.     if( ourRsrc == nil )
  1116.         return nil;
  1117.     
  1118.     return (**(USBGlobalsHandle**)ourRsrc);
  1119. }
  1120.  
  1121. /*-----------------------------------------------------------------------------*
  1122.  
  1123.     RemoveGlobalStorage
  1124.     
  1125.     Desc:        Removes our global storage area
  1126.  
  1127.     In:            none
  1128.  
  1129.     Out:        Handle to our global storage
  1130.     
  1131.     History:
  1132.     
  1133.     9  Jun 98    gp        Dispose of our global rsrc after removing it
  1134.     26 Mar 98    gp        Release model index storage
  1135.     25 Mar 98    gp        Created
  1136.  
  1137.  *-----------------------------------------------------------------------------*/
  1138. void    RemoveGlobalStorage(void)
  1139. {
  1140.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  1141.     Handle                ourRsrc;
  1142.     
  1143.     gGlobals = GetGlobalStorage();
  1144.     if( gGlobals != nil ) {
  1145.         // dispose of index ptr
  1146.         
  1147.         if ( (**gGlobals).modelIndex != nil )
  1148.         {
  1149.             DisposePtr( (Ptr) (**gGlobals).modelIndex );
  1150.         }
  1151.              
  1152.         // remove our global handle
  1153.         HUnlock( (Handle) gGlobals );
  1154.         DisposeHandle( (Handle) gGlobals );
  1155.         // remove our rsrc for global address storage
  1156.         ourRsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1157.         RemoveResource( ourRsrc );
  1158.         DisposeHandle( ourRsrc );
  1159.     }
  1160. }
  1161. // eof
  1162.